<?php
/**
 * 阿里支付.
 * User: chan
 * Date: 2017/8/7 18:10
 */

namespace app\api\service;

use app\api\logic\Order;
use app\api\logic\PayBeans;
use think\Db;
use think\Loader;
use think\Log;

Loader::import('AliPay.AopClient', EXTEND_PATH, '.php');
Loader::import('AliPay.AlipayConfig', EXTEND_PATH, '.php');
Loader::import('AliPay.AlipayTradeAppPayRequest', EXTEND_PATH, '.php');

class AliPay
{
    public function pay($orderData)
    {
        $aop = new \AopClient;
        $aop->gatewayUrl = \AlipayConfig::GATEWAY_URL;
        $aop->appId = \AlipayConfig::APPID;
        $aop->rsaPrivateKey = \AlipayConfig::RSAPRIVATE_KEY;
        $aop->format = \AlipayConfig::FORMAT;
        $aop->charset = \AlipayConfig::CHARSET;
        $aop->signType = \AlipayConfig::SIGN_TYPE;
        $aop->alipayrsaPublicKey = \AlipayConfig::ALIPAYRSAPUBLIC_KEY;
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
        $request = new \AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数，这里只需要传入业务参数
        $bizcontent = "{\"body\":\"" . $orderData['title'] . "\","
            . "\"subject\": \"" . $orderData['title'] . "\","
            . "\"out_trade_no\": \"" . $orderData['pay_sn'] . "\","
            . "\"timeout_express\": \"30m\","
            . "\"total_amount\": \"" . $orderData['charges'] . "\","
            . "\"product_code\":\"QUICK_MSECURITY_PAY\""
            . "}";
        $request->setNotifyUrl(\AlipayConfig::SETNOTIFY_URL);
        $request->setBizContent($bizcontent);
        //这里和普通的接口调用不同，使用的是sdkExecute
        $response = $aop->sdkExecute($request);
        //htmlspecialchars是为了输出到页面时防止被浏览器将关键参数html转义，实际打印到日志以及http传输不会有这个问题
        return array('orderString' => $response);//就是orderString 可以直接给客户端请求，无需再做处理。
    }

    //异步通知
    public function notify()
    {
        $aop = new \AopClient;
        $aop->alipayrsaPublicKey = \AlipayConfig::ALIPAYRSAPUBLIC_KEY;
        //验证签名
        $flag = $aop->rsaCheckV1($_POST, NULL, "RSA2");
        if ($flag) {//验证成功
            $out_trade_no = $_POST['out_trade_no'];//订单编号
            $trade_no = $_POST['trade_no']; //支付宝交易号
            $app_id = $_POST['app_id']; //商户id
            $seller_id = $_POST['seller_id']; //卖家支付宝用户号
            $trade_status = $_POST['trade_status'];//交易状态
            $total_amount = $_POST['total_amount'];//t	订单金额
            /**
             * 业务处理
             * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
             * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
             * 3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
             * 4、验证app_id是否为该商户本身。
             * 上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。
             * 在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。
             * 在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
             */
            if ($trade_status == 'TRADE_SUCCESS' || $_POST['trade_status'] == 'TRADE_FINISHED') {

                $model_pay_log = db('pay_log');
                $pay_log = $model_pay_log->where(array('pay_sn' => $out_trade_no))->find();
                if (empty($pay_log)) {
                    Log::write("找不到支付单号：" . $out_trade_no . "的订单");
                    return false;
                }
                if ($pay_log['status'] == PAY_SUCCESS) {
                    Log::write("该订单已支付，支付单号：" . $out_trade_no . "的订单",'info');
                    return false;
                }
                if($pay_log['money'] != $total_amount){
                    Log::write("该订单的金额与实际支付不符，支付单号：" . $out_trade_no . "的订单",'info');
                    return false;
                }

                $result = (new Order())->afterPay($pay_log,2);
                if(array_key_exists('message',$result)) return false;

            }
            exit('success');//请不要修改或删除
        } else {//验证成功
            exit('fail');
        }

    }
}